;*******************************************************************************
; (C) 2006 Keith S. Robertson - IE_BIF.ASM
;-------------------------------------------------------------------------------
;
; All Infinity Engines Functions, Variables & Data Related to BIF Format Files
;
;*******************************************************************************
.386	

;INCLUDE IE.MAC	; Macros
INCLUDE masm32.inc

INCLUDELIB masm32.lib

include debug.inc
includelib debug.lib


.CONST

.DATA
___BIFCSig			db "BIFC",0
___BIF_Sig			db "BIF ",0
___BIFFSig			db "BIFF",0
___BIFFileSignature	db 4 dup (0)

.DATA?
;__hBIFFileHandle	DD	?	; IE BIF File Handle
;__BIFC_Uncompressed	DD	?	; True or False if BIFC file has been uncompressed
;__BIFC_Data			DD	?	; Pointer to allocated memory for BIFC uncompressed data
hWnd				dd ?


.CODE

BIFOpenFile				PROC 	BIFFileName:DWORD
	Invoke IEOpenFile, BIFFileName
	ret
BIFOpenFile 			ENDP


BIFCloseFile 			PROC 	hBIFFile:DWORD
	Invoke IECloseFile,hBIFFile
	ret
BIFCloseFile 			ENDP


BIFReadHeader			PROC 	hBIFFile:DWORD, pBIFHeaderData:DWORD
	LOCAL lnBytesRead:DWORD

	Invoke IEFileSignature, hBIFFile, Addr ___BIFFileSignature, BIF_ACCESS_FILE ; Get file signature and then check it
	
	; Invoke MessageBox, 0, Addr ___BIFFileSignature,  CTEXT("IE Lib"), MB_OK
	
	; Read First 20 Bytes of File = BIF Header (Before File & Tile Entry Tables)
	Invoke SetFilePointerEx, hBIFFile, 0, NULL, NULL, FILE_BEGIN
	Invoke ReadFile, hBIFFile, pBIFHeaderData, 20, Addr lnBytesRead, NULL
	.if eax != 0
		mov eax, TRUE ; all was ok so return true, otherwise we return false
	.else
		mov eax, FALSE ; An error occured reading file so return false
	.endif
	ret
BIFReadHeader 			ENDP


BIFReadBody				PROC 	hBIFFile:DWORD, pBIFBodyData:DWORD
	LOCAL lnFileSize:DWORD
	LOCAL lnBytesRead:DWORD

	Invoke IEFileSignature, hBIFFile, Addr ___BIFFileSignature, BIF_ACCESS_FILE

	; Read From Byte 20 of File = BIF Body (Including File & Tile Entry Tables)
	Invoke GetFileSizeEx, hBIFFile, lnFileSize
	Invoke SetFilePointerEx, hBIFFile, 20, NULL, NULL, FILE_BEGIN
	mov ebx, lnFileSize
	sub ebx, 20
	Invoke ReadFile, hBIFFile, pBIFBodyData, ebx, addr lnBytesRead, NULL
	.if eax != 0
		mov eax, TRUE
	.else
		mov eax, FALSE
	.endif
	ret
BIFReadBody 			ENDP


BIFReadAll			PROC 	hBIFFile:DWORD, pBIFFileData:DWORD
	LOCAL lnFileSize:DWORD
	LOCAL lnBytesRead:DWORD

	Invoke IEFileSignature, hBIFFile, Addr ___BIFFileSignature, BIF_ACCESS_FILE

	; Read Entire File From Byte 0 of File = BIF File (Including Header, File & Tile Entry Tables & Body)
	Invoke GetFileSizeEx, hBIFFile, lnFileSize
	Invoke SetFilePointerEx, hBIFFile, 20, NULL, NULL, FILE_BEGIN
	Invoke ReadFile, hBIFFile, pBIFFileData, lnFileSize, addr lnBytesRead, NULL
	.if eax != 0
		mov eax, TRUE
	.else
		mov eax, FALSE
	.endif
	ret
BIFReadAll 			ENDP




BIFUncompress 			PROC 	hBIFFile:DWORD, pData:DWORD
	ret

BIFUncompress endp


BIFIsCompressed 		PROC	hFile_or_pMem:DWORD, AccessType:DWORD
	Invoke IEFileSignature, hFile_or_pMem, Addr ___BIFFileSignature, AccessType
	Invoke cmpmem, Addr ___BIFFileSignature, Addr ___BIFCSig, 4		
	.if eax == 0	
		Invoke cmpmem, Addr ___BIFFileSignature, Addr ___BIF_Sig, 4	
		.if eax == 0	
			mov eax, FALSE
		.else
			mov eax, TRUE
		.endif		
	.else
		mov eax, TRUE
	.ENDIF
	ret
BIFIsCompressed 		ENDP


BIFUncompressedSize		PROC	hFile_or_pMem:DWORD, pBuffer:DWORD, AccessType:DWORD

	; 0x0008  	4 (dword)  	Length of filename
	; 0x000c 	variable (ASCIIZ char array) 	Filename (length specified by previous field)
	; sizeof(filename)+0x0010 	4 (dword) 	Uncompressed data length
	; Get length of Filename at offset 8h
	; Add length of Filename to 10h to get offset to uncompressed data length

	LOCAL hFile:DWORD
	LOCAL pMem:DWORD
	LOCAL lnFilenameLength:DWORD
	LOCAL lnOffsetToUncompressedSize:DWORD
	LOCAL lnBytesRead:DWORD
	
	mov eax, hFile_or_pMem
	
	.IF AccessType == BIF_ACCESS_FILE	; 0 
		mov hFile, eax
		Invoke SetFilePointerEx, hFile, 8, NULL, NULL, FILE_BEGIN
		Invoke ReadFile, hFile, lnFilenameLength, 4, addr lnBytesRead, NULL
		.if eax != 0
			mov ebx, lnFilenameLength ; store filename length to local var
			add ebx, 16	; add 10h (16d) to filename length to calc offset to read
			mov lnOffsetToUncompressedSize, ebx	; save this calculated offset
			Invoke SetFilePointerEx, hFile, lnOffsetToUncompressedSize, NULL, NULL, FILE_BEGIN
			Invoke ReadFile, hFile, pBuffer, 4, addr lnBytesRead, NULL ; write to 
			.IF eax != 0	
				mov eax, TRUE			
			.else
				mov eax, FALSE
			.endif
		.else
			mov eax, FALSE
		.endif
		
	.else	; BIF_ACCESS_MEM ; 1
		mov pMem, eax
		lea ebx, pMem
		add ebx, 8
		Invoke MemCopy, pBuffer, ebx, 4
		mov eax, TRUE
	.endif
	ret
BIFUncompressedSize 	ENDP


BIFCompressedSize		PROC	hFile_or_pMem:DWORD, pBuffer:DWORD, AccessType:DWORD

	; 0x0008  	4 (dword)  	Length of filename
	; 0x000c 	variable (ASCIIZ char array) 	Filename (length specified by previous field)
	; sizeof(filename)+0x0010 	4 (dword) 	Uncompressed data length
	; sizeof(filename)+0x0014  	4 (dword)  	Compressed data length
	; Get length of Filename at offset 8h
	; Add length of Filename to 14h to get offset to uncompressed data length

	LOCAL hFile:DWORD
	LOCAL pMem:DWORD
	LOCAL lnFilenameLength:DWORD
	LOCAL lnOffsetToCompressedSize:DWORD
	LOCAL lnBytesRead:DWORD	
	
	mov eax, hFile_or_pMem
	
	.IF AccessType == BIF_ACCESS_FILE	; 0 
		mov hFile, eax
		Invoke SetFilePointerEx, hFile, 8, NULL, NULL, FILE_BEGIN
		Invoke ReadFile, hFile, lnFilenameLength, 4, addr lnBytesRead, NULL
		.if eax != 0
			mov ebx, lnFilenameLength ; store filename length to local var
			add ebx, 16	; add 14h (20d) to filename length to calc offset to read
			mov lnOffsetToCompressedSize, ebx	; save this calculated offset
			Invoke SetFilePointerEx, hFile, lnOffsetToCompressedSize, NULL, NULL, FILE_BEGIN
			Invoke ReadFile, hFile, pBuffer, 4, addr lnBytesRead, NULL ; write to 
			.IF eax != 0	
				mov eax, TRUE			
			.else
				mov eax, FALSE
			.endif
		.else
			mov eax, FALSE
		.endif
		
	.else	; BIF_ACCESS_MEM ; 1
		mov pMem, eax
		lea ebx, pMem
		add ebx, 20d
		Invoke MemCopy, pBuffer, ebx, 4
		mov eax, TRUE
	.endif
	ret
BIFCompressedSize		ENDP
	

BIFCompressedData		PROC	hFile_or_pMem:DWORD, pBuffer:DWORD, AccessType:DWORD

	; 0x0008  	4 (dword)  	Length of filename
	; 0x000c 	variable (ASCIIZ char array) 	Filename (length specified by previous field)
	; sizeof(filename)+0x0010 	4 (dword) 	Uncompressed data length
	; sizeof(filename)+0x0014  	4 (dword)  	Compressed data length
	; sizeof(filename)+0x0018  	variable (raw data)  	Compressed data (length in bytes specified by previous field)
	; Get length of Filename at offset 8h
	; Add length of Filename to 18h to get offset to uncompressed data length

	LOCAL hFile:DWORD
	LOCAL pMem:DWORD
	LOCAL lnFilenameLength:DWORD
	LOCAL lnOffsetToCompressedData:DWORD
	LOCAL lnBytesRead:DWORD	
		
	mov eax, hFile_or_pMem
	
	.IF AccessType == BIF_ACCESS_FILE	; 0 
		mov hFile, eax
		Invoke SetFilePointerEx, hFile, 8, NULL, NULL, FILE_BEGIN
		Invoke ReadFile, hFile, lnFilenameLength, 4, addr lnBytesRead, NULL
		.if eax != 0
			mov ebx, lnFilenameLength ; store filename length to local var
			add ebx, 16	; add 18h (24d) to filename length to calc offset to read
			mov lnOffsetToCompressedData, ebx	; save this calculated offset
			Invoke SetFilePointerEx, hFile, lnOffsetToCompressedData, NULL, NULL, FILE_BEGIN
			Invoke ReadFile, hFile, pBuffer, 4, addr lnBytesRead, NULL ; write to 
			.IF eax != 0	
				mov eax, TRUE			
			.else
				mov eax, FALSE
			.endif
		.else
			mov eax, FALSE
		.endif
		
	.else	; BIF_ACCESS_MEM ; 1
		mov pMem, eax
		lea ebx, pMem
		add ebx, 24d
		Invoke MemCopy, pBuffer, ebx, 4
		mov eax, TRUE
	.endif
	ret
BIFCompressedData		ENDP


BIFCompressedName 		PROC 	hFile_or_pMem:DWORD, pBuffer:DWORD, AccessType:DWORD
	LOCAL lnBytesRead:DWORD	
	ret
BIFCompressedName 		ENDP


BIFCompressedType 		PROC 	hFile_or_pMem:DWORD, pBuffer:DWORD, AccessType:DWORD
	Invoke IEFileSignature, hFile_or_pMem, pBuffer, AccessType
	ret
BIFCompressedType		ENDP




BIFNoFileEntries		PROC	hFile_or_pMem:DWORD, pBuffer:DWORD, AccessType:DWORD
	LOCAL hFile:DWORD
	LOCAL pMem:DWORD
	LOCAL lnBytesRead:DWORD	
		
	mov eax, hFile_or_pMem
	
	.IF AccessType == BIF_ACCESS_FILE	; 0 
		mov hFile, eax
		Invoke SetFilePointerEx, hFile, 8, NULL, NULL, FILE_BEGIN
		Invoke ReadFile, hFile, pBuffer, 4, addr lnBytesRead, NULL
		.if eax != 0
			mov eax, TRUE
		.else
			mov eax, FALSE
		.endif
		
	.else	; BIF_ACCESS_MEM ; 1
		mov pMem, eax
		lea ebx, pMem
		add ebx, 8
		Invoke MemCopy, pBuffer, ebx, 4
		mov eax, TRUE
	.endif
	ret
BIFNoFileEntries		ENDP
	
	
BIFNoTileEntries		PROC	hFile_or_pMem:DWORD, pBuffer:DWORD, AccessType:DWORD
	LOCAL hFile:DWORD
	LOCAL pMem:DWORD
	LOCAL lnBytesRead:DWORD	
		
	mov eax, hFile_or_pMem
	
	.IF AccessType == BIF_ACCESS_FILE	; 0 
		mov hFile, eax
		Invoke SetFilePointerEx, hFile, 12, NULL, NULL, FILE_BEGIN
		Invoke ReadFile, hFile, pBuffer, 4, addr lnBytesRead, NULL
		.if eax != 0
			mov eax, TRUE
		.else
			mov eax, FALSE
		.endif
		
	.else	; BIF_ACCESS_MEM ; 1
		mov pMem, eax
		lea ebx, pMem
		add ebx, 12
		Invoke MemCopy, pBuffer, ebx, 4
		mov eax, TRUE
	.endif
	ret
BIFNoTileEntries		ENDP
	


	
BIFFileEntriesOffset	PROC	hFile_or_pMem:DWORD, pBuffer:DWORD, AccessType:DWORD
	LOCAL hFile:DWORD
	LOCAL pMem:DWORD
	LOCAL lnBytesRead:DWORD	
		
	mov eax, hFile_or_pMem
	
	.IF AccessType == BIF_ACCESS_FILE	; 0 
		mov hFile, eax
		Invoke SetFilePointerEx, hFile, 16, NULL, NULL, FILE_BEGIN
		Invoke ReadFile, hFile, pBuffer, 4, addr lnBytesRead, NULL
		.if eax != 0
			mov eax, TRUE
		.else
			mov eax, FALSE
		.endif
		
	.else	; BIF_ACCESS_MEM ; 1
		mov pMem, eax
		lea ebx, pMem
		add ebx, 16
		Invoke MemCopy, pBuffer, ebx, 4
		mov eax, TRUE
	.endif
	ret
BIFFileEntriesOffset	ENDP


BIFFileEntryResLocator	PROC	hFile_or_pMem:DWORD, pBuffer:DWORD, AccessType:DWORD, FileEntryIndex:DWORD
	; FileEntryIndex is used to access a specified record entry in this table
	LOCAL lnNoFileEntries
	LOCAL lnFileEntryOffset
	LOCAL lnFileEntryIndexOffset
	LOCAL hFile:DWORD
	LOCAL pMem:DWORD
	LOCAL lnBytesRead:DWORD	
	
	mov eax, hFile_or_pMem
	mov hFile, eax
	mov pMem, eax
	
	; Get No File Entries - Needed for checking we didnt specify too many
	Invoke BIFNoFileEntries, hFile_or_pMem, Addr lnNoFileEntries, AccessType

	; Get File Entry Offset - Needed for later calculations below
	Invoke BIFFileEntriesOffset, hFile_or_pMem, Addr lnFileEntryOffset, AccessType
		
	; Check that we havent specified too high a file entry for the amount that is supposed to be in this BIF file
	mov ecx, FileEntryIndex
	.if ecx > lnNoFileEntries
		mov eax, FALSE	; Ret false if we have
		ret
	.endif
	
	.if ecx == 0
		mov eax, FALSE	; ret false if we have specified 0
		ret
	.endif
	
	; Calculate out what offset to ResLocator is and store it - each FileEntry record is 16 bytes long. Rec 1 = 0 x 16 = 0. Rec 2 = 1 x 16 = 16
	dec FileEntryIndex
	mov eax, FileEntryIndex

	Invoke IntMul, eax, 16
	mov ebx, lnFileEntryOffset
	add eax, ebx
	; Add 0 to this total give us the offset to ResLocator
	mov lnFileEntryIndexOffset, eax	
	
	.IF AccessType == BIF_ACCESS_FILE	; 0 
		Invoke SetFilePointerEx, hFile, lnFileEntryIndexOffset, NULL, NULL, FILE_BEGIN
		Invoke ReadFile, hFile, pBuffer, 4, addr lnBytesRead, NULL
		.if eax != 0
			mov eax, TRUE
		.else
			mov eax, FALSE
		.endif
		
	.else	; BIF_ACCESS_MEM ; 1
		mov pMem, eax
		lea ebx, pMem
		add ebx, lnFileEntryIndexOffset
		Invoke MemCopy, pBuffer, ebx, 4
		mov eax, TRUE
	.endif
	ret
BIFFileEntryResLocator	ENDP


BIFFileEntryResOffset	PROC	hFile_or_pMem:DWORD, pBuffer:DWORD, AccessType:DWORD, FileEntryIndex:DWORD
	; FileEntryIndex is used to access a specified record entry in this table
	LOCAL lnNoFileEntries
	LOCAL lnFileEntryOffset
	LOCAL lnFileEntryIndexOffset
	LOCAL hFile:DWORD
	LOCAL pMem:DWORD
	LOCAL lnBytesRead:DWORD	
	
	mov eax, hFile_or_pMem
	mov hFile, eax
	mov pMem, eax
	
	; Get No File Entries - Needed for checking we didnt specify too many
	Invoke BIFNoFileEntries, hFile_or_pMem, Addr lnNoFileEntries, AccessType

	; Get File Entry Offset - Needed for later calculations below
	Invoke BIFFileEntriesOffset, hFile_or_pMem, Addr lnFileEntryOffset, AccessType
		
	; Check that we havent specified too high a file entry for the amount that is supposed to be in this BIF file
	mov ecx, FileEntryIndex
	.if ecx > lnNoFileEntries
		mov eax, FALSE	; Ret false if we have
		ret
	.endif
	
	.if ecx == 0
		mov eax, FALSE	; ret false if we have specified 0
		ret
	.endif
	
	; Calculate out what offset to ResLocator is and store it - each FileEntry record is 16 bytes long. Rec 1 = 0 x 16 = 0. Rec 2 = 1 x 16 = 16
	dec FileEntryIndex
	mov eax, FileEntryIndex

	Invoke IntMul, eax, 16
	mov ebx, lnFileEntryOffset
	add eax, ebx
	add eax, 4 ; Add 4 to this total to give us offset to ResOffset
	mov lnFileEntryIndexOffset, eax	
	PrintDec lnFileEntryIndexOffset	
	
	.IF AccessType == BIF_ACCESS_FILE	; 0 
		Invoke SetFilePointerEx, hFile, lnFileEntryIndexOffset, NULL, NULL, FILE_BEGIN
		Invoke ReadFile, hFile, pBuffer, 4, addr lnBytesRead, NULL
		.if eax != 0
			mov eax, TRUE
			PrintDec pBuffer
		.else
			mov eax, FALSE
		.endif
		
	.else	; BIF_ACCESS_MEM ; 1
		mov pMem, eax
		lea ebx, pMem
		add ebx, lnFileEntryIndexOffset
		Invoke MemCopy, pBuffer, ebx, 4
		mov eax, TRUE
	.endif
	ret
BIFFileEntryResOffset	ENDP


BIFFileEntryResSize 	PROC	hFile_or_pMem:DWORD, pBuffer:DWORD, AccessType:DWORD, FileEntryIndex:DWORD
	; FileEntryIndex is used to access a specified record entry in this table
	LOCAL lnNoFileEntries
	LOCAL lnFileEntryOffset
	LOCAL lnFileEntryIndexOffset
	LOCAL hFile:DWORD
	LOCAL pMem:DWORD
	LOCAL lnBytesRead:DWORD	
	
	mov eax, hFile_or_pMem
	mov hFile, eax
	mov pMem, eax
	
	; Get No File Entries - Needed for checking we didnt specify too many
	Invoke BIFNoFileEntries, hFile_or_pMem, Addr lnNoFileEntries, AccessType

	; Get File Entry Offset - Needed for later calculations below
	Invoke BIFFileEntriesOffset, hFile_or_pMem, Addr lnFileEntryOffset, AccessType
		
	; Check that we havent specified too high a file entry for the amount that is supposed to be in this BIF file
	mov ecx, FileEntryIndex
	.if ecx > lnNoFileEntries
		mov eax, FALSE	; Ret false if we have
		ret
	.endif
	
	.if ecx == 0
		mov eax, FALSE	; ret false if we have specified 0
		ret
	.endif
	
	; Calculate out what offset to ResLocator is and store it - each FileEntry record is 16 bytes long. Rec 1 = 0 x 16 = 0. Rec 2 = 1 x 16 = 16
	dec FileEntryIndex
	mov eax, FileEntryIndex

	Invoke IntMul, eax, 16
	mov ebx, lnFileEntryOffset
	add eax, ebx
	add eax, 8 ; Add 8 to this total to give us offset to ResSize
	mov lnFileEntryIndexOffset, eax	
	PrintDec lnFileEntryIndexOffset	
		
	
	.IF AccessType == BIF_ACCESS_FILE	; 0 
		Invoke SetFilePointerEx, hFile, lnFileEntryIndexOffset, NULL, NULL, FILE_BEGIN
		Invoke ReadFile, hFile, pBuffer, 4, addr lnBytesRead, NULL
		.if eax != 0
			mov eax, TRUE
		.else
			mov eax, FALSE
		.endif
		
	.else	; BIF_ACCESS_MEM ; 1
		mov pMem, eax
		lea ebx, pMem
		add ebx, lnFileEntryIndexOffset
		Invoke MemCopy, pBuffer, ebx, 4
		mov eax, TRUE
	.endif
	ret
BIFFileEntryResSize		ENDP


BIFFileEntryResType 	PROC	hFile_or_pMem:DWORD, pBuffer:DWORD, AccessType:DWORD, FileEntryIndex:DWORD
	; FileEntryIndex is used to access a specified record entry in this table
	LOCAL lnNoFileEntries
	LOCAL lnFileEntryOffset
	LOCAL lnFileEntryIndexOffset
	LOCAL hFile:DWORD
	LOCAL pMem:DWORD
	LOCAL lnBytesRead:DWORD	
	
	mov eax, hFile_or_pMem
	mov hFile, eax
	mov pMem, eax
	
	; Get No File Entries - Needed for checking we didnt specify too many
	Invoke BIFNoFileEntries, hFile_or_pMem, Addr lnNoFileEntries, AccessType

	; Get File Entry Offset - Needed for later calculations below
	Invoke BIFFileEntriesOffset, hFile_or_pMem, Addr lnFileEntryOffset, AccessType
		
	; Check that we havent specified too high a file entry for the amount that is supposed to be in this BIF file
	mov ecx, FileEntryIndex
	.if ecx > lnNoFileEntries
		mov eax, FALSE	; Ret false if we have
		ret
	.endif
	
	.if ecx == 0
		mov eax, FALSE	; ret false if we have specified 0
		ret
	.endif
	
	; Calculate out what offset to ResLocator is and store it - each FileEntry record is 16 bytes long. Rec 1 = 0 x 16 = 0. Rec 2 = 1 x 16 = 16
	dec FileEntryIndex
	mov eax, FileEntryIndex

	Invoke IntMul, eax, 16
	mov ebx, lnFileEntryOffset
	add eax, ebx
	add eax, 12 ; Add 12 to this total to give us offset to ResType
	mov lnFileEntryIndexOffset, eax	
	PrintDec lnFileEntryIndexOffset	
		
	
	.IF AccessType == BIF_ACCESS_FILE	; 0 
		Invoke SetFilePointerEx, hFile, lnFileEntryIndexOffset, NULL, NULL, FILE_BEGIN
		Invoke ReadFile, hFile, pBuffer, 4, addr lnBytesRead, NULL
		.if eax != 0
			mov eax, TRUE
		.else
			mov eax, FALSE
		.endif
		
	.else	; BIF_ACCESS_MEM ; 1
		mov pMem, eax
		lea ebx, pMem
		add ebx, lnFileEntryIndexOffset
		Invoke MemCopy, pBuffer, ebx, 4
		mov eax, TRUE
	.endif
	ret
BIFFileEntryResType		ENDP


BIFFileEntry			PROC	hFile_or_pMem:DWORD, pBuffer:DWORD, AccessType:DWORD, FileEntryIndex:DWORD
	; FileEntryIndex is used to access a specified record entry in this table
	LOCAL lnNoFileEntries
	LOCAL lnFileEntryOffset
	LOCAL lnFileEntryIndexOffset
	LOCAL hFile:DWORD
	LOCAL pMem:DWORD
	LOCAL lnBytesRead:DWORD	
	
	mov eax, hFile_or_pMem
	mov hFile, eax
	mov pMem, eax
	
	; Get No File Entries - Needed for checking we didnt specify too many
	Invoke BIFNoFileEntries, hFile_or_pMem, Addr lnNoFileEntries, AccessType

	; Get File Entry Offset - Needed for later calculations below
	Invoke BIFFileEntriesOffset, hFile_or_pMem, Addr lnFileEntryOffset, AccessType
		
	; Check that we havent specified too high a file entry for the amount that is supposed to be in this BIF file
	mov ecx, FileEntryIndex
	.if ecx > lnNoFileEntries
		mov eax, FALSE	; Ret false if we have
		ret
	.endif
	
	.if ecx == 0
		mov eax, FALSE	; ret false if we have specified 0
		ret
	.endif
	
	; Calculate out what offset to ResLocator is and store it - each FileEntry record is 16 bytes long. Rec 1 = 0 x 16 = 0. Rec 2 = 1 x 16 = 16
	mov ebx, FileEntryIndex
	sub ebx, 1
	mov ecx, 16
	mul eax
	mov ebx, lnFileEntryOffset
	add eax, ebx
	mov lnFileEntryIndexOffset, eax	
		
	
	.IF AccessType == BIF_ACCESS_FILE	; 0 
		Invoke SetFilePointerEx, hFile, lnFileEntryIndexOffset, NULL, NULL, FILE_BEGIN
		Invoke ReadFile, hFile, pBuffer, 16, addr lnBytesRead, NULL		; Return 16 bytes - full record for specified entry
		.if eax != 0
			mov eax, TRUE
		.else
			mov eax, FALSE
		.endif
		
	.else	; BIF_ACCESS_MEM ; 1
		mov pMem, eax
		lea ebx, pMem
		add ebx, lnFileEntryIndexOffset
		Invoke MemCopy, pBuffer, ebx, 16
		mov eax, TRUE
	.endif	
	ret
BIFFileEntry 			ENDP




BIFTileEntriesOffset	PROC 	USES eax ebx hFile_or_pMem:DWORD, pBuffer:DWORD, AccessType:DWORD
	; Get File Entries Offset
	; Get File Entries and Multiply by 16 (no of bytes in file entry record table
	; add this to File Entries Offset
	LOCAL lnNoFileEntries:DWORD
	LOCAL lnFileEntriesOffset:DWORD	
		
	; Get File Entry Offset 
	Invoke BIFFileEntriesOffset, hFile_or_pMem, Addr lnFileEntriesOffset, AccessType
;	PrintDec lnFileEntriesOffset
	
	; Get No File Entries 
	Invoke BIFNoFileEntries, hFile_or_pMem, Addr lnNoFileEntries, AccessType	
;	PrintDec lnNoFileEntries

	mov eax, lnNoFileEntries
	Invoke IntMul, eax, 16
	mov ebx, lnFileEntriesOffset
	add eax, ebx
	mov ebx, [pBuffer]
	mov [ebx], eax
	ret
BIFTileEntriesOffset 	ENDP	


BIFTileEntryResLocator 	PROC	hFile_or_pMem:DWORD, pBuffer:DWORD, AccessType:DWORD, TileEntryIndex:DWORD
	; FileEntryIndex is used to access a specified record entry in this table
	LOCAL lnNoTileEntries
	LOCAL lnTileEntryOffset
	LOCAL lnTileEntryIndexOffset
	LOCAL hFile:DWORD
	LOCAL pMem:DWORD
	LOCAL lnBytesRead:DWORD	
	
	mov eax, hFile_or_pMem
	mov hFile, eax
	mov pMem, eax
	
	; Get No Tile Entries - Needed for checking we didnt specify too many
	Invoke BIFNoTileEntries, hFile_or_pMem, Addr lnNoTileEntries, AccessType

	; Get Tile Entry Offset - Needed for later calculations below
	Invoke BIFTileEntriesOffset, hFile_or_pMem, Addr lnTileEntryOffset, AccessType
		
	; Check that we havent specified too high a tile entry for the amount that is supposed to be in this BIF file
	mov ecx, TileEntryIndex
	.if ecx > lnNoTileEntries
		mov eax, FALSE	; Ret false if we have
		ret
	.endif
	
	.if ecx == 0
		mov eax, FALSE	; ret false if we have specified 0
		ret
	.endif
	
	; Calculate out what offset to ResLocator is and store it - each TileEntry record is 16 bytes long. Rec 1 = 0 x 16 = 0. Rec 2 = 1 x 16 = 16
	mov ebx, TileEntryIndex
	sub ebx, 1
	mov ecx, 16
	mul eax
	mov ebx, lnTileEntryOffset
	add eax, ebx
	; Add 0 to this total give us the offset to ResLocator
	mov lnTileEntryIndexOffset, eax		
	
	.IF AccessType == BIF_ACCESS_FILE	; 0 
		Invoke SetFilePointerEx, hFile, lnTileEntryIndexOffset, NULL, NULL, FILE_BEGIN
		Invoke ReadFile, hFile, pBuffer, 4, addr lnBytesRead, NULL
		.if eax != 0
			mov eax, TRUE
		.else
			mov eax, FALSE
		.endif
		
	.else	; BIF_ACCESS_MEM ; 1
		mov pMem, eax
		lea ebx, pMem
		add ebx, lnTileEntryIndexOffset
		Invoke MemCopy, pBuffer, ebx, 4
		mov eax, TRUE
	.endif
	ret
BIFTileEntryResLocator	ENDP


BIFTileEntryResOffset 	PROC	hFile_or_pMem:DWORD, pBuffer:DWORD, AccessType:DWORD, TileEntryIndex:DWORD
	; FileEntryIndex is used to access a specified record entry in this table
	LOCAL lnNoTileEntries
	LOCAL lnTileEntryOffset
	LOCAL lnTileEntryIndexOffset
	LOCAL hFile:DWORD
	LOCAL pMem:DWORD
	LOCAL lnBytesRead:DWORD	
	
	mov eax, hFile_or_pMem
	mov hFile, eax
	mov pMem, eax
	
	; Get No Tile Entries - Needed for checking we didnt specify too many
	Invoke BIFNoTileEntries, hFile_or_pMem, Addr lnNoTileEntries, AccessType

	; Get Tile Entry Offset - Needed for later calculations below
	Invoke BIFTileEntriesOffset, hFile_or_pMem, Addr lnTileEntryOffset, AccessType
		
	; Check that we havent specified too high a tile entry for the amount that is supposed to be in this BIF file
	mov ecx, TileEntryIndex
	.if ecx > lnNoTileEntries
		mov eax, FALSE	; Ret false if we have
		ret
	.endif
	
	.if ecx == 0
		mov eax, FALSE	; ret false if we have specified 0
		ret
	.endif
	
	; Calculate out what offset to ResLocator is and store it - each TileEntry record is 16 bytes long. Rec 1 = 0 x 16 = 0. Rec 2 = 1 x 16 = 16
	mov ebx, TileEntryIndex
	sub ebx, 1
	mov ecx, 16
	mul eax
	mov ebx, lnTileEntryOffset
	add eax, ebx
	add eax, 4 ; Add 4 to this total to give us offset to ResOffset
	mov lnTileEntryIndexOffset, eax	
		
	
	.IF AccessType == BIF_ACCESS_FILE	; 0 
		Invoke SetFilePointerEx, hFile, lnTileEntryIndexOffset, NULL, NULL, FILE_BEGIN
		Invoke ReadFile, hFile, pBuffer, 4, addr lnBytesRead, NULL
		.if eax != 0
			mov eax, TRUE
		.else
			mov eax, FALSE
		.endif
		
	.else	; BIF_ACCESS_MEM ; 1
		mov pMem, eax
		lea ebx, pMem
		add ebx, lnTileEntryIndexOffset
		Invoke MemCopy, pBuffer, ebx, 4
		mov eax, TRUE
	.endif
	ret	
BIFTileEntryResOffset 	ENDP


BIFTileEntryResNoTiles	PROC	hFile_or_pMem:DWORD, pBuffer:DWORD, AccessType:DWORD, TileEntryIndex:DWORD
	; FileEntryIndex is used to access a specified record entry in this table
	LOCAL lnNoTileEntries
	LOCAL lnTileEntryOffset
	LOCAL lnTileEntryIndexOffset
	LOCAL hFile:DWORD
	LOCAL pMem:DWORD
	LOCAL lnBytesRead:DWORD	
	
	mov eax, hFile_or_pMem
	mov hFile, eax
	mov pMem, eax
	
	; Get No Tile Entries - Needed for checking we didnt specify too many
	Invoke BIFNoTileEntries, hFile_or_pMem, Addr lnNoTileEntries, AccessType

	; Get Tile Entry Offset - Needed for later calculations below
	Invoke BIFTileEntriesOffset, hFile_or_pMem, Addr lnTileEntryOffset, AccessType
		
	; Check that we havent specified too high a tile entry for the amount that is supposed to be in this BIF file
	mov ecx, TileEntryIndex
	.if ecx > lnNoTileEntries
		mov eax, FALSE	; Ret false if we have
		ret
	.endif
	
	.if ecx == 0
		mov eax, FALSE	; ret false if we have specified 0
		ret
	.endif
	
	; Calculate out what offset to ResLocator is and store it - each TileEntry record is 16 bytes long. Rec 1 = 0 x 16 = 0. Rec 2 = 1 x 16 = 16
	mov ebx, TileEntryIndex
	sub ebx, 1
	mov ecx, 16
	mul eax
	mov ebx, lnTileEntryOffset
	add eax, ebx
	add eax, 8 ; Add 8 to this total to give us offset to ResNoTiles
	mov lnTileEntryIndexOffset, eax	
		
	
	.IF AccessType == BIF_ACCESS_FILE	; 0 
		Invoke SetFilePointerEx, hFile, lnTileEntryIndexOffset, NULL, NULL, FILE_BEGIN
		Invoke ReadFile, hFile, pBuffer, 4, addr lnBytesRead, NULL
		.if eax != 0
			mov eax, TRUE
		.else
			mov eax, FALSE
		.endif
		
	.else	; BIF_ACCESS_MEM ; 1
		mov pMem, eax
		lea ebx, pMem
		add ebx, lnTileEntryIndexOffset
		Invoke MemCopy, pBuffer, ebx, 4
		mov eax, TRUE
	.endif
	ret		
BIFTileEntryResNoTiles	ENDP	


BIFTileEntryResSize 	PROC	hFile_or_pMem:DWORD, pBuffer:DWORD, AccessType:DWORD, TileEntryIndex:DWORD
	; FileEntryIndex is used to access a specified record entry in this table
	LOCAL lnNoTileEntries
	LOCAL lnTileEntryOffset
	LOCAL lnTileEntryIndexOffset
	LOCAL hFile:DWORD
	LOCAL pMem:DWORD
	LOCAL lnBytesRead:DWORD	
	
	mov eax, hFile_or_pMem
	mov hFile, eax
	mov pMem, eax
	
	; Get No Tile Entries - Needed for checking we didnt specify too many
	Invoke BIFNoTileEntries, hFile_or_pMem, Addr lnNoTileEntries, AccessType

	; Get Tile Entry Offset - Needed for later calculations below
	Invoke BIFTileEntriesOffset, hFile_or_pMem, Addr lnTileEntryOffset, AccessType
		
	; Check that we havent specified too high a tile entry for the amount that is supposed to be in this BIF file
	mov ecx, TileEntryIndex
	.if ecx > lnNoTileEntries
		mov eax, FALSE	; Ret false if we have
		ret
	.endif
	
	.if ecx == 0
		mov eax, FALSE	; ret false if we have specified 0
		ret
	.endif
	
	; Calculate out what offset to ResLocator is and store it - each TileEntry record is 16 bytes long. Rec 1 = 0 x 16 = 0. Rec 2 = 1 x 16 = 16
	mov ebx, TileEntryIndex
	sub ebx, 1
	mov ecx, 16
	mul eax
	mov ebx, lnTileEntryOffset
	add eax, ebx
	add eax, 12 ; Add 12 to this total to give us offset to ResSize
	mov lnTileEntryIndexOffset, eax	
		
	
	.IF AccessType == BIF_ACCESS_FILE	; 0 
		Invoke SetFilePointerEx, hFile, lnTileEntryIndexOffset, NULL, NULL, FILE_BEGIN
		Invoke ReadFile, hFile, pBuffer, 4, addr lnBytesRead, NULL
		.if eax != 0
			mov eax, TRUE
		.else
			mov eax, FALSE
		.endif
		
	.else	; BIF_ACCESS_MEM ; 1
		mov pMem, eax
		lea ebx, pMem
		add ebx, lnTileEntryIndexOffset
		Invoke MemCopy, pBuffer, ebx, 4
		mov eax, TRUE
	.endif
	ret		
BIFTileEntryResSize		ENDP


BIFTileEntryResType 	PROC	hFile_or_pMem:DWORD, pBuffer:DWORD, AccessType:DWORD, TileEntryIndex:DWORD
	; TileEntryIndex is used to access a specified record entry in this table
	LOCAL lnNoTileEntries
	LOCAL lnTileEntryOffset
	LOCAL lnTileEntryIndexOffset
	LOCAL hFile:DWORD
	LOCAL pMem:DWORD
	LOCAL lnBytesRead:DWORD	
	
	mov eax, hFile_or_pMem
	mov hFile, eax
	mov pMem, eax
	
	; Get No Tile Entries - Needed for checking we didnt specify too many
	Invoke BIFNoTileEntries, hFile_or_pMem, Addr lnNoTileEntries, AccessType

	; Get Tile Entry Offset - Needed for later calculations below
	Invoke BIFTileEntriesOffset, hFile_or_pMem, Addr lnTileEntryOffset, AccessType
		
	; Check that we havent specified too high a Tile entry for the amount that is supposed to be in this BIF file
	mov ecx, TileEntryIndex
	.if ecx > lnNoTileEntries
		mov eax, FALSE	; Ret false if we have
		ret
	.endif
	
	.if ecx == 0
		mov eax, FALSE	; ret false if we have specified 0
		ret
	.endif
	
	; Calculate out what offset to ResLocator is and store it - each TileEntry record is 16 bytes long. Rec 1 = 0 x 16 = 0. Rec 2 = 1 x 16 = 16
	mov ebx, TileEntryIndex
	sub ebx, 1
	mov ecx, 16
	mul eax
	mov ebx, lnTileEntryOffset
	add eax, ebx
	add eax, 16 ; Add 16 to this total to give us offset to ResType
	mov lnTileEntryIndexOffset, eax	
		
	
	.IF AccessType == BIF_ACCESS_FILE	; 0 
		Invoke SetFilePointerEx, hFile, lnTileEntryIndexOffset, NULL, NULL, FILE_BEGIN
		Invoke ReadFile, hFile, pBuffer, 4, addr lnBytesRead, NULL
		.if eax != 0
			mov eax, TRUE
		.else
			mov eax, FALSE
		.endif
		
	.else	; BIF_ACCESS_MEM ; 1
		mov pMem, eax
		lea ebx, pMem
		add ebx, lnTileEntryIndexOffset
		Invoke MemCopy, pBuffer, ebx, 4
		mov eax, TRUE
	.endif	
	ret
BIFTileEntryResType		ENDP


BIFTileEntry			PROC	hFile_or_pMem:DWORD, pBuffer:DWORD, AccessType:DWORD, TileEntryIndex:DWORD
	; TileEntryIndex is used to access a specified record entry in this table
	LOCAL lnNoTileEntries
	LOCAL lnTileEntryOffset
	LOCAL lnTileEntryIndexOffset
	LOCAL hFile:DWORD
	LOCAL pMem:DWORD
	LOCAL lnBytesRead:DWORD	
	
	mov eax, hFile_or_pMem
	mov hFile, eax
	mov pMem, eax
	
	; Get No Tile Entries - Needed for checking we didnt specify too many
	Invoke BIFNoTileEntries, hFile_or_pMem, Addr lnNoTileEntries, AccessType

	; Get Tile Entry Offset - Needed for later calculations below
	Invoke BIFTileEntriesOffset, hFile_or_pMem, Addr lnTileEntryOffset, AccessType
		
	; Check that we havent specified too high a tile entry for the amount that is supposed to be in this BIF file
	mov ecx, TileEntryIndex
	.if ecx > lnNoTileEntries
		mov eax, FALSE	; Ret false if we have
		ret
	.endif
	
	.if ecx == 0
		mov eax, FALSE	; ret false if we have specified 0
		ret
	.endif
	
	; Calculate out what offset to ResLocator is and store it - each TileEntry record is 20 bytes long. Rec 1 = 0 x 20 = 0. Rec 2 = 1 x 20 = 20
	mov ebx, TileEntryIndex
	sub ebx, 1
	mov ecx, 20
	mul eax
	mov ebx, lnTileEntryOffset
	add eax, ebx
	mov lnTileEntryIndexOffset, eax	
		
	
	.IF AccessType == BIF_ACCESS_FILE	; 0 
		Invoke SetFilePointerEx, hFile, lnTileEntryIndexOffset, NULL, NULL, FILE_BEGIN
		Invoke ReadFile, hFile, pBuffer, 20, addr lnBytesRead, NULL		; Return 20 bytes - full record for specified entry
		.if eax != 0
			mov eax, TRUE
		.else
			mov eax, FALSE
		.endif
		
	.else	; BIF_ACCESS_MEM ; 1
		mov pMem, eax
		lea ebx, pMem
		add ebx, lnTileEntryIndexOffset
		Invoke MemCopy, pBuffer, ebx, 16
		mov eax, TRUE
	.endif	
	ret
BIFTileEntry			ENDP













	
